(add-to-load-path (dirname (current-filename)))

(use-modules (ice-9 getopt-long))

(define (string-exact-integer? str)
  (exact-integer? (string->number str)))

;; First we define an option specification.
(define option-spec
  ;; - Accept two options "version" and "help".
  ;; - They can be abbreviated by the single characters "v" and "h".
  ;; - The (value #f) tells getopt-long, that these options do not accept a value.
  `((version (single-char #\v) (value #f))
    (help    (single-char #\h) (value #f))
    (user-name (value #t) (required? #f))
    (times-hello (value #t)
                 (single-char #\n)
                 (required? #f)
                 (predicate ,string-exact-integer?))))

;; For each intended argument we have an association list which stores (property-name property-value).
;; The following properties are available:
;;
;; single-char (Single character abbreviation for the option.)
;; value (Does the option need a value? #t/#f/'optional, Is the option a flag?)
;; required? (#t/#f)
;; predicate (specify a procedure that takes the option's value as a string and returns #t or #f depending on whether the string is an acceptable input or not.)

;; Then we let getopt-long parse the arguments given.
(define options (getopt-long (command-line) option-spec))

;; Access the value of the parsed options.
;; - It takes the options that were parsed,
;; - the options name we inquire about as a symbol,
;; - and a default value, in case the option was not specified on command line.
(option-ref options 'help #f)

;; Now a program that uses this stuff.
(define (main)
  (let* ([help-wanted (option-ref options 'help #f)]
         [version-wanted (option-ref options 'version #f)]
         [user-name (option-ref options 'user-name #f)]
         [times-say-hello (string->number (option-ref options 'times-hello "1"))])
    (cond [(or version-wanted help-wanted)
           (when version-wanted
             (display "command-line-arguments.scm 1.0.0\n"))
           (when help-wanted
             (display
              (string-join '(""
                             "getopt-long-example [options]"
                             "-v,  --version  Display version"
                             "-h,  --help     Display this help"
                             "")
                           "\n")))]
          [else
           (do ([i 0 (1+ i)])
               ([>= i times-say-hello])
             (display (simple-format #f "Hello, ~a!\n" (if user-name
                                                           user-name
                                                           "World"))))])))

(main)
